package com.world.tg.aop;

import com.world.tg.anno.CacheFind;
import com.world.tg.util.ObjectMapperUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;

import java.util.Arrays;

@Component
@Aspect //表示切面类
public class RedisAop {

    @Autowired
    private Jedis jedis;

    /**
     * 实现AOP业务
     * 1、拦截指定注解
     * 2、利用环绕通知实现
     * 实现步骤：
     *      1、获取key 获取注解，从注解中获取key
     *      2、检验redis是否有值
     * @param joinPoint 必须位于参数的第一位
     * @param cacheFind
     * @return
     */
    @Around("@annotation(cacheFind)")
    public Object around(ProceedingJoinPoint joinPoint, CacheFind cacheFind){
        Object result = null;
        // key=业务名称：：参数
        String key = cacheFind.key();
        String args = Arrays.toString(joinPoint.getArgs());
        key = key + "::" + args;

        // 校验是否有值
        if(jedis.exists(key)){
            String json = jedis.get(key);
            MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
            Class returnType = methodSignature.getReturnType();

            result = ObjectMapperUtil.toOBJ(json,returnType);
            System.out.println("AOP查询redis缓存");
        }else {
            // redis中没有数据，所以需要查询数据库，将数据保存到缓存中
            try{
                result = joinPoint.proceed();
                String json = ObjectMapperUtil.toJSON(result);
                // 是否设定超时时间
                if(cacheFind.seconds() > 0){
                    jedis.setex(key,cacheFind.seconds(),json);
                }else {
                    jedis.set(key,json);
                }
                System.out.println("AOP查询数据库");
            }catch (Throwable throwable){
                throwable.printStackTrace();
            }
        }
        return result;
    }
}
